package com.sky.aop;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 切面类
 *
 * @Author: Zhy
 * @Date: 2025-01-15 18:16
 * @Version: 1.0
 */
@Aspect
@Component
@Slf4j
public class AutoFileAspect {
	/**
	 * 切点方法
	 *
	 * @return:
	 * @param:
	 */
	@Pointcut("@annotation(com.sky.annotation.AutoFill)")
	public void pt1() { }

	/**
	 * 增强
	 *
	 * @return:
	 * @param:
	 */
	@Before("pt1()")
	public void fillProperty(JoinPoint jp) {
		log.warn("指定填充属性 AOP 增强：{}", jp);

		try {
			// 1. 拿到参数
			Object[] args = jp.getArgs();
			if (Objects.isNull(args) || args.length == 0) {
				return;
			}
			Object pojo = args[0];

			// 2. 反射获取方法上的 @AutoFill 注解
			MethodSignature signature = (MethodSignature) jp.getSignature();
			Method method = signature.getMethod();
			AutoFill autoFill = method.getAnnotation(AutoFill.class);
			if (Objects.isNull(autoFill)) {
				return;
			}

			LocalDateTime now = LocalDateTime.now();
			Long currentId = BaseContext.getCurrentId();
			// 3. 获取注解属性
			Class<?> clazz = pojo.getClass();
			if (OperationType.INSERT == autoFill.value()) {
				// 新增操作，填充四个属性
				Method setCreateTimeMethod = clazz.getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
				Method setUpdateTimeMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
				Method setCreateUserMethod = clazz.getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
				Method setUpdateUserMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

				// 调用方法
				setCreateTimeMethod.invoke(pojo, now);
				setUpdateTimeMethod.invoke(pojo, now);
				setCreateUserMethod.invoke(pojo, currentId);
				setUpdateUserMethod.invoke(pojo, currentId);
			} else if (OperationType.UPDATE == autoFill.value()) {
				// 更新操作，填充两个属性
				Method setUpdateTimeMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
				Method setUpdateUserMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

				// 调用方法
				setUpdateTimeMethod.invoke(pojo, now);
				setUpdateUserMethod.invoke(pojo, currentId);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}
